package com.derbysoft.ota.application.translator.rs;

import java.math.BigInteger;

import com.derbysoft.modules.eip.translator.Translator;
import com.derbysoft.ota.interfaces.protocol._2009a.BasicPropertyInfoType;
import com.derbysoft.ota.interfaces.protocol._2009a.DateTimeSpanType;
import com.derbysoft.ota.interfaces.protocol._2009a.GuestCountType;
import com.derbysoft.ota.interfaces.protocol._2009a.HotelReservationType;
import com.derbysoft.ota.interfaces.protocol._2009a.RatePlanType;
import com.derbysoft.ota.interfaces.protocol._2009a.RoomTypeType;
import com.derbysoft.ota.interfaces.protocol._2009a.RoomStayType.RatePlans;
import com.derbysoft.ota.interfaces.protocol._2009a.RoomStayType.RoomRates;
import com.derbysoft.ota.interfaces.protocol._2009a.RoomStayType.RoomTypes;
import com.derbysoft.ota.interfaces.protocol._2009a.RoomStayType.RoomRates.RoomRate;
import com.derbysoft.ota.interfaces.protocol._2009a.RoomStaysType.RoomStay;
import com.derbysoft.remote.dswitch.hotel.dto.HotelRefDTO;
import com.derbysoft.remote.dswitch.hotel.dto.ReservationRoomStayDTO;
import com.google.inject.Inject;
import com.googlecode.functionalcollections.FunctionalIterables;

public class RoomStayRSTranslator implements Translator<RoomStayRSSource, RoomStay> {
	
	private Translator<ReservationRoomStayDTO, RoomRate> resRoomRateTranlator;
	
	@Inject
	public RoomStayRSTranslator(Translator<ReservationRoomStayDTO, RoomRate> resRoomRateTranlator) {
		this.resRoomRateTranlator = resRoomRateTranlator;
	}

	@Override
	public RoomStay translate(RoomStayRSSource source) {
		RoomStay roomStay = new RoomStay();
		roomStay.setBasicPropertyInfo(basicProperty(source.getHotelRef()));
		roomStay.setTimeSpan(timeSpan(source.getOtaRQ()));
		roomStay.setGuestCounts(guestCounts(source.getOtaRQ()));
		
		ReservationRoomStayDTO sourceRoomStay = source.getSwitchRoomStay();

		roomStay.setRoomTypes(new RoomTypes());
		roomStay.getRoomTypes().getRoomType().add(roomType(sourceRoomStay));
		
		roomStay.setRatePlans(new RatePlans());
		roomStay.getRatePlans().getRatePlan().add(ratePlan(sourceRoomStay));
		
		roomStay.setRoomRates(new RoomRates());
		roomStay.getRoomRates().getRoomRate().add(roomRate(sourceRoomStay));
		
		return roomStay;
	}

	private DateTimeSpanType timeSpan(HotelReservationType otaRQ) {
		return roomStayRQ(otaRQ).getTimeSpan();
	}
	
	private GuestCountType guestCounts(HotelReservationType otaRQ) {
		return roomStayRQ(otaRQ).getGuestCounts();
	}

	private RoomStay roomStayRQ(HotelReservationType otaRQ) {
		return FunctionalIterables.make(
			otaRQ.getRoomStays().getRoomStay()
		).messagedIterator("Please provide us exactly 1 RoomStay.").next();
	}

	private BasicPropertyInfoType basicProperty(HotelRefDTO hotelRef) {
		BasicPropertyInfoType property = new BasicPropertyInfoType();
		property.setHotelCode(hotelRef.getCode());
		property.setHotelName(hotelRef.getName());
		property.setBrandCode(hotelRef.getBrandCode());
		property.setChainCode(hotelRef.getChainCode());
		return property;
	}
	
	private RoomTypeType roomType(ReservationRoomStayDTO sourceRoomStay) {
		RoomTypeType roomType = new RoomTypeType();
		roomType.setRoomTypeCode(sourceRoomStay.getRoomTypeCode());
		roomType.setRoomType(sourceRoomStay.getRoomTypeName());
		roomType.setNumberOfUnits(BigInteger.valueOf(sourceRoomStay.getNumberOfUnits()));
		return roomType;
	}
	
	private RatePlanType ratePlan(ReservationRoomStayDTO sourceRoomStay) {
		RatePlanType ratePlan = new RatePlanType();
		ratePlan.setRatePlanCode(sourceRoomStay.getRatePlanCode());
		ratePlan.setRatePlanName(sourceRoomStay.getRatePlanName());
		return ratePlan;
	}
	
	private RoomRate roomRate(ReservationRoomStayDTO switchRoomStay) {
		return resRoomRateTranlator.translate(switchRoomStay);
	}

}
